#ifndef BSP_UTILS_H
#define BSP_UTILS_H

#ifdef __cplusplus
extern "C" {
#endif


#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include <Arduino.h>



#define RUN_ONCE(something)     do{something;}while(0)
#define BITSET(data,pos)		((data) |= (1u)<<(pos))
#define BITCLR(data,pos)		((data) &= ~((1u)<<(pos)))
#define BITREV(data,pos)		((data) ^= ~((1u)<<(pos)))
#define BITGET(data,pos)		(((data)>>(pos)) & (1u))

// 仅限于相同数据类型,不同类型会在产生强制类型转换
#define	SWAP_UNITYPE(n1,n2)	do{(n1)=(n1)+(n2);(n2)=(n1)-(n2);(n1)=(n1)-(n2)}while(0)
#define	MAX(n1,n2)			    ((n1)>(n2)?(n1):(n2))
#define	MIN(n1,n2)			    ((n1)<(n2)?(n1):(n2))
#define LIMIT_CHECK(val,min,max)    ((val)>=(max)?(max):((val)<=(min)?(min):(val)))

#define GET_SIZEOF_ARR_D1(arr) ((uint32_t)sizeof(arr)/sizeof(arr[0]))
#define GET_SIZEOF_ARR_D2(arr) ((uint32_t)sizeof(arr)/sizeof(arr[0][0]))//ONLY for dimension = 2
#define GET_ARR_ROWS(arr) (GET_SIZEOF_ARR_D1(arr))
#define GET_ARR_COLS(arr) (GET_SIZEOF_ARR_D2(arr)/GET_SIZEOF_ARR_D1(arr))//ONLY for dimension = 2
#define COUNTOF(__BUFFER__)   (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))

// 将dest数组完全填充
#define STRCPY(dest,src) do{strncpy(dest,src,(sizeof(dest)-1));dest[(sizeof(dest)-1)]='\0';}while(0)
// 将dest数组完全拼接
#define STRCAT(dest,src) do{strncat(dest,src,sizeof(dest)-strlen(dest)-1);dest[(sizeof(dest)-1)]='\0';}while(0)

#define FLOAT_EPS 0.000001f /* ISO标准为0.000001f */
#define DOUBLE_EPS 1e-15
#define FLOAT_EQUAL_ZERO(float_num)      ((float_num>=-FLOAT_EPS)&&(float_num<=FLOAT_EPS))


/*[!] */
#define BSP_PRINTF(...)			do{Serial.printf(__VA_ARGS__);fflush(stdout);}while(0)

    

#define BYTE_TO_BINARY_PATTERN_8BITS "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY_8BITS(byte)  \
							  (byte & 0x80 ? '1' : '0'), \
							  (byte & 0x40 ? '1' : '0'), \
							  (byte & 0x20 ? '1' : '0'), \
							  (byte & 0x10 ? '1' : '0'), \
							  (byte & 0x08 ? '1' : '0'), \
							  (byte & 0x04 ? '1' : '0'), \
							  (byte & 0x02 ? '1' : '0'), \
							  (byte & 0x01 ? '1' : '0')
#define PrintBin8(x)		do{Serial.printf(#x " = " BYTE_TO_BINARY_PATTERN_8BITS "\r\n", BYTE_TO_BINARY_8BITS((uint8_t)x));fflush(stdout);}while(0)

#define BYTE_TO_BINARY_PATTERN_32BITS "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY_32BITS(byte)  \
							  (byte & 0x80000000 ? '1' : '0'), \
							  (byte & 0x40000000 ? '1' : '0'), \
							  (byte & 0x20000000 ? '1' : '0'), \
							  (byte & 0x10000000 ? '1' : '0'), \
							  (byte & 0x08000000 ? '1' : '0'), \
							  (byte & 0x04000000 ? '1' : '0'), \
							  (byte & 0x02000000 ? '1' : '0'), \
							  (byte & 0x01000000 ? '1' : '0'), \
							  (byte & 0x00800000 ? '1' : '0'), \
							  (byte & 0x00400000 ? '1' : '0'), \
							  (byte & 0x00200000 ? '1' : '0'), \
							  (byte & 0x00100000 ? '1' : '0'), \
							  (byte & 0x00080000 ? '1' : '0'), \
							  (byte & 0x00040000 ? '1' : '0'), \
							  (byte & 0x00020000 ? '1' : '0'), \
							  (byte & 0x00010000 ? '1' : '0'), \
							  (byte & 0x00008000 ? '1' : '0'), \
							  (byte & 0x00004000 ? '1' : '0'), \
							  (byte & 0x00002000 ? '1' : '0'), \
							  (byte & 0x00001000 ? '1' : '0'), \
							  (byte & 0x00000800 ? '1' : '0'), \
							  (byte & 0x00000400 ? '1' : '0'), \
							  (byte & 0x00000200 ? '1' : '0'), \
							  (byte & 0x00000100 ? '1' : '0'), \
							  (byte & 0x00000080 ? '1' : '0'), \
							  (byte & 0x00000040 ? '1' : '0'), \
							  (byte & 0x00000020 ? '1' : '0'), \
							  (byte & 0x00000010 ? '1' : '0'), \
							  (byte & 0x00000008 ? '1' : '0'), \
							  (byte & 0x00000004 ? '1' : '0'), \
							  (byte & 0x00000002 ? '1' : '0'), \
							  (byte & 0x00000001 ? '1' : '0')
#define PrintBin32(x)		do{Serial.printf(#x " = " BYTE_TO_BINARY_PATTERN_32BITS "\r\n", BYTE_TO_BINARY_32BITS((uint32_t)x));fflush(stdout);}while(0)


#define PrintHex(x)		    do{Serial.printf(#x " = 0x%02X\r\n", x);fflush(stdout);}while(0)
#define PrintInt(x)		    do{Serial.printf(#x" = %d\r\n", x);fflush(stdout);}while(0)
#define PrintLong(x)		do{Serial.printf(#x" = %ld\r\n", x);fflush(stdout);}while(0)
#define PrintFloat(x)       do{Serial.printf(#x" = %f\r\n", x);fflush(stdout);}while(0)



uint8_t CalcSum(uint8_t *arr, uint16_t len);
uint8_t GetHigh4bit(uint8_t data);
uint8_t GetLow4bit(uint8_t data);

bool Bsp_IsLittleEndian(void);

bool WildcardMatch(const char *sPat, const char *sStr);


uint32_t x_power_y(uint32_t x, uint8_t y);
uint32_t NextPowerOf2(uint32_t number);
int split(char *src,const char *separator,char **dest);



/* Types */
typedef union {
	float type_float32;
	uint8_t type_uint8[4];
} float32;






#ifdef __cplusplus
}
#endif

#endif /* BSP_UTILS_H */
/*______________________________END___________________________________________*/
